﻿#ifndef LIBRARY_FACTORY_H
#define LIBRARY_FACTORY_H

#include <QString>

class QLibrary;
class QMutex;

/**
 * @brief 一个用于从动态库加载设备插件实例的静态工厂类。
 *
 * 该类的公共接口设计为仅通过库名解析。它内部遵循一个约定：
 * 目标库必须导出一个C风格的函数 `void* instance()`，该函数负责创建并返回设备实例。
 * 工厂会加载库、找到此函数、调用它，并返回其结果。
 */
class LibraryFactory
{
private:
    // 私有化构造和析构，强制该类仅作为静态工具使用。
    LibraryFactory() = default;
    ~LibraryFactory() = default;

public:
    // 禁止拷贝和赋值。
    LibraryFactory(const LibraryFactory &) = delete;
    LibraryFactory &operator=(const LibraryFactory &) = delete;

    /**
     * @brief 从指定动态库加载一个设备实例。
     *
     * 该函数加载库，查找名为 "instance" 的导出函数，调用该函数，
     * 并返回其返回的 void* 指针。
     *
     * @param dllName 动态库的路径或名称。
     * @return 如果成功，返回一个由库内 "instance" 函数创建的实例指针；
     *         如果库加载失败、"instance"函数未找到或该函数返回nullptr，则返回 nullptr。
     */
    static void *resolve(const QString &dllName);

    /**
     * @brief  resolve，用于自动将返回的 void* 指针转换为正确的设备接口类型。
     *
     * @tparam T 期望返回的指针类型 (例如: IDevice* 或 IDeviceIO*)。
     * @param dllName 动态库的路径或名称。
     * @return 如果成功，返回类型为 T 的实例指针；否则返回 nullptr。
     *
     * @example
     * IDeviceIO* io = LibraryFactory::resolve<IDeviceIO*>("networkc");
     */
    template<typename T>
    static T resolve(const QString &dllName)
    {
        return static_cast<T>(LibraryFactory::resolve(dllName));
    }

    /**
     * @brief 手动清理所有已加载的库。
     * 通常不需要调用，内部的自动清理器会在程序退出时处理。
     */
    static void cleanup();

private:
    // 静态成员，用于缓存库和实现线程安全
    static QMap<QString, QLibrary *> s_libraries;
    static QMutex s_mutex;
};

#include <type_traits>

// 关闭并销毁（用于 IDevice* 或 IDeviceIO* 的 unique_ptr 句柄）
template<typename Handle>
inline void closeAndReset(Handle &h)
{
    if (!h)
        return;
    h->close(); // IDevice::close 或 IDeviceIO::close
    h.reset();  // 触发 ManagedDeviceDeleter -> DeviceInstanceManager::destroyInstance
}

// 仅销毁（不调用 close），常用于 IO：设备已关过 IO，这里只释放对象
template<typename Handle>
inline void resetOnly(Handle &h)
{
    if (!h)
        return;
    h.reset();
}

// 批量工具（C++14 参数包展开）
template<typename... Handles>
inline void closeAndResetAll(Handles &...hs)
{
    int unused[] = {(closeAndReset(hs), 0)...};
    (void)unused;
}

template<typename... Handles>
inline void resetAll(Handles &...hs)
{
    int unused[] = {(resetOnly(hs), 0)...};
    (void)unused;
}

#endif // LIBRARY_FACTORY_H
